/* eslint-disable no-console */
let warned: Record<string, boolean> = {};

/**
 * 在开发环境下输出错误信息
 *
 * 该函数旨在在开发环境下，当验证失败时，向控制台输出警告信息
 * 它通过检查 NODE_ENV 环境变量确保只在非生产环境下运行，以避免在生产环境中出现不必要的输出
 * 此外，它还检查 console 是否定义，以确保在某些限制性的环境中不会抛出错误
 *
 * @param valid - 表示验证是否通过的布尔值如果为 false，则会输出警告信息
 * @param message - 如果验证失败，将要输出的警告信息字符串
 */
export function warning(valid: boolean, message: string): void {
  // Support uglify
  if (process.env.NODE_ENV !== 'production' && !valid && console !== undefined) {
    console.error(`Warning: ${message}`);
  }
}

/**
 * 在非生产环境中输出警告信息
 *
 * 该函数用于在开发和测试环境中输出一些重要的笔记信息，以帮助开发者更好地理解和维护代码
 * 它通过检查当前环境是否为非生产环境，以及验证输入的有效性来决定是否输出信息
 *
 * @param valid - 表示信息有效性，如果为false，则会输出信息
 * @param message - 要输出的信息内容
 */
export function note(valid: boolean, message: string): void {
  // Support uglify
  if (process.env.NODE_ENV !== 'production' && !valid && console !== undefined) {
    console.warn(`Note: ${message}`);
  }
}

export function resetWarned(): void {
  warned = {};
}

/**
 * 调用给定的方法，仅当验证无效且尚未发出警告时才调用
 * 此函数的目的是在验证失败时发出警告，确保每个警告只显示一次
 *
 * @param method - 一个接受两个参数（valid和message）的回调函数，用于处理验证结果和消息
 * @param valid - 验证结果，true表示验证通过，false表示验证失败
 * @param message - 验证消息，当验证失败时会传递此消息给回调函数
 */
export function call(method: (valid: boolean, message: string) => void, valid: boolean, message: string): void {
  // 检查验证结果是否无效且该警告消息尚未被触发过
  if (!valid && !warned[message]) {
    // 调用回调函数，向其传递false和警告消息
    method(false, message);
    // 将此警告消息标记为已发送，以避免重复警告
    warned[message] = true;
  }
}

/**
 * 根据给定的条件触发一次性警告
 * 该函数用于在某些条件下向开发者发出警告，以避免重复警告的干扰
 * 它通过调用 `call` 函数来实现警告的触发，确保警告只在条件不满足时触发一次
 *
 * @param valid 指示是否满足条件的布尔值如果条件满足（即 `valid` 为 true），则不会发出警告
 * @param message 如果条件不满足时要显示的警告信息
 */
export function warningOnce(valid: boolean, message: string): void {
  call(warning, valid, message);
}

/**
 * 在非生产环境中输出一次性警告信息
 *
 * 该函数旨在用于开发和调试阶段，通过输出警告信息来提醒开发者某些代码执行的合法性或状态
 * 它通过调用`note`函数来实现警告信息的输出，但不会在生产环境中产生任何效果
 *
 * @param valid 指示是否有效如果为false，则会输出警告信息
 * @param message 要输出的警告信息内容
 */
export function noteOnce(valid: boolean, message: string): void {
  call(note, valid, message);
}

export default warningOnce;
/* eslint-enable */
